package com.xique.park.mq.consumer;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.xique.common.core.constant.Constants;
import com.xique.common.core.utils.AliossUtil;
import com.xique.park.bean.domain.*;
import com.xique.park.bean.dto.ParkInDto;
import com.xique.park.mq.bean.ParkOutMsg;
import com.xique.park.service.biz.service.IParkWxMessageSendBizService;
import com.xique.park.service.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author shd
 * @create 2022/7/29 10:41
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ParkOutFinishMqConsumer {

    private final IParkThirdPartyPushService parkThirdPartyPushService;

    private final MsgIdempotentService msgIdempotentService;

    private final IParkMqFailMsgService parkMqFailMsgService;

    private final IParkLaneService parkLaneService;

    private final IParkInService parkInService;

    private final IParkingOrderService parkingOrderService;

    private final AliossUtil aliossUtil;

    private final IParkWxMessageSendBizService parkWxMessageSendBizService;

    public void receive(ParkOutMsg parkOutMsg) {
        try {
            Long msgId = parkOutMsg.getMsgId();
            if (null != msgId) {
                // 插入数据库，防止重复消费
                if (saveParkMqMsg(parkOutMsg)) {
                    ParkOut parkOut = parkOutMsg.getParkOut();
                    if (null != parkOut) {
                        Long parkId = parkOut.getParkId();
                        ParkThirdPartyPush parkThirdPartyPush = getParkThirdPartyPush(parkId);
                        // 判断车场是否需要推送进场记录
                        if (parkThirdPartyPush != null && parkThirdPartyPush.getOutRecordPush() == Constants.TRUE) {
                            // 组织信息
                            Map<String, Object> paramMap = paramMap(parkOut);

                            // 推送
                            push(parkThirdPartyPush, paramMap, parkId, parkOut);
                        }

                        // 进场消息推送到对应用户的公众号
                        parkWxMessageSendBizService.delayParkOutFinishProcess(parkOut);
                    } else {
                        log.warn("[出场通知]-出场消息中的入场信息为空，{}", parkOutMsg);
                    }
                } else {
                    log.warn("[出场通知]-消息已经被消费过了，{}", parkOutMsg);
                }
            } else {
                log.warn("[出场通知]-出场消息ID为空，{}", parkOutMsg);
            }
        } catch (Exception e) {
            // 将处理失败的消息存入数据库
            saveParkMqFailMsg(parkOutMsg);

            log.error("[出场通知]-消息处理异常，异常信息：{}，{}", e.getMessage(), parkOutMsg);
            e.printStackTrace();
        }
    }

    private boolean saveParkMqMsg(ParkOutMsg parkOutMsg) {
        String msgMd5 = MD5.create().digestHex(JSON.toJSONString(parkOutMsg));
        MsgIdempotent parkMqMsg = new MsgIdempotent();
        parkMqMsg.setMsgMd5(msgMd5);
        parkMqMsg.setCreateTime(new Date());
        return msgIdempotentService.save(parkMqMsg);
    }

    private ParkThirdPartyPush getParkThirdPartyPush(Long parkId) {
        return parkThirdPartyPushService.selectOneByParkId(parkId);
    }

    private Map<String, Object> paramMap(ParkOut parkOut) {
        Map<String, Object> paramMap = new HashMap<>(17);
        Long parkId = parkOut.getParkId();
        String parkingSerial = parkOut.getParkingSerial();

        paramMap.put("parkId", parkOut.getParkId());
        paramMap.put("carPlate", parkOut.getOutCarPlate());
        paramMap.put("parkingSerial", parkingSerial);
        paramMap.put("mngType", parkOut.getMngType());
        paramMap.put("outPic", StrUtil.isNotBlank(parkOut.getOutPic()) ? aliossUtil.getJzyGetObjectUrl(parkOut.getOutPic()) : "");
        paramMap.put("outTime", parkOut.getOutTime());
        paramMap.put("outLaneName", getLaneName(parkOut.getOutLaneId()));
        paramMap.put("outStatus", parkOut.getStatus());

        ParkInDto parkInDto = getParkIn(parkId, parkingSerial);
        if (null != parkInDto) {
            // 获取入场信息
            paramMap.put("inTime", parkInDto.getInTime());
            paramMap.put("inPic", StrUtil.isNotBlank(parkInDto.getInPic()) ? aliossUtil.getJzyGetObjectUrl(parkInDto.getInPic()).toString() : "");
            paramMap.put("inLaneName", parkInDto.getLaneName());
            paramMap.put("inStatus", parkInDto.getStatus());
            paramMap.put("mngTypeName", parkInDto.getMngName());
        }

        // 获取订单信息，停车总金额、提前支付金额、优惠金额、待支付费用
        ParkingOrder parkingOrder = getParkingOrder(parkId, parkingSerial);
        if (null != parkingOrder) {
            paramMap.put("totalFee", parkingOrder.getTotalFee());
            paramMap.put("paidFee", parkingOrder.getPaidFee());
            paramMap.put("couponFee", parkingOrder.getCouponFee());
            paramMap.put("payFee", parkingOrder.getPayFee());

        }

        return paramMap;
    }

    private ParkingOrder getParkingOrder(Long parkId, String parkingSerial) {
        ParkingOrder parkingOrderSearch = new ParkingOrder();
        parkingOrderSearch.setParkId(parkId);
        parkingOrderSearch.setParkingSerial(parkingSerial);
        List<ParkingOrder> parkingOrderList = parkingOrderService.selectParkingOrderList(parkingOrderSearch);
        if (CollUtil.isNotEmpty(parkingOrderList)) {
            return parkingOrderList.get(0);
        } else {
            return null;
        }
    }

    private ParkInDto getParkIn(Long parkId, String parkingSerial) {
        List<ParkInDto> parkInDtoList = parkInService.selectParkInByParkingSerial(parkId, parkingSerial);
        if (CollUtil.isNotEmpty(parkInDtoList)) {
            return parkInDtoList.get(0);
        }
        return null;
    }

    private String getLaneName(Long laneId) {
        ParkLane parkLane = parkLaneService.selectParkLaneById(laneId);
        if (null != parkLane) {
            return parkLane.getName();
        }
        return "";
    }

    private void push(ParkThirdPartyPush parkThirdPartyPush, Map<String, Object> paramMap, Long parkId, ParkOut parkOut) {
        String outRecordPushUrl = parkThirdPartyPush.getOutRecordPushUrl();
        if (StrUtil.isNotBlank(outRecordPushUrl)) {
            String json = JSON.toJSONString(paramMap);
            String httpResponse = HttpUtil.post(outRecordPushUrl, json);
            log.info("[出场通知]-出场记录推送地址：{}，推送信息：{}，推送结果：{}", outRecordPushUrl, paramMap, httpResponse);
        } else {
            log.warn("[出场通知]-车场未配置出场记录推送地址，车场：{}，{}", parkId, parkOut);
        }
    }

    private void saveParkMqFailMsg(ParkOutMsg parkOutMsg) {
        ParkMqFailMsg parkMqFailMsg = new ParkMqFailMsg();
        parkMqFailMsg.setMsgId(parkOutMsg.getMsgId());
        parkMqFailMsg.setMsg(JSON.toJSONString(parkOutMsg));
        parkMqFailMsg.setCreateTime(new Date());
        parkMqFailMsgService.save(parkMqFailMsg);
    }

}
